/**
 * 表单方案渲染页面Js
 */
import FormSolutionApi from "@/common/api/form/formSolution.js";
import FormPrintLodopApi from "@/common/api/form/formPrintLodop.js";
import ButtonShow from "./ButtonShow";
import DialogBox from "@/assets/js/dialogBox.js";
import router from '@/router';
import rxAjax from '@/assets/js/ajax.js';
import PdfFunction from "../js/PdfFunction.js";
import Print from "../js/Print.js";
import {Util} from '@lowcode/jpaas-base-lib';
import { mapState } from 'pinia'
import userUser from "@/stores/userUser";
import FlowFunctions from "@/views/modules/bpm/OpenDoc/js/FlowFunctions";
import FormLiteFlowApi from '@/common/api/form/formLiteFlow.js'
import FormPcApi from '@/common/api/form/FormPcApi.js'
import AppUtil from "../../../../assets/js/AppUtil";

export default {
    mixins:[PdfFunction,Print,FlowFunctions],
    data() {
        return {
            //根实例
            rootVm: true,
            canStartFlow: false,
            flowInstId:"",
            localDefId:"",
            //表单方案别名
            formSolutionAlias: "",
            //表单的表单别名
            formAlias: "",
            //表单主键
            formPkId:"",
            //表单参数
            formParams:"",
            //当前表单方案
            formSolution:"",
            //表单方案按钮
            buttons:[],
            //表单主键
            idField:"",
            processConfig: {
                buttons: [],
                startConfirm: false,
                fillOpinion: false,
                assignFlowUsers: false,
                assignBatchFlowUsers: false,
                startCalFlowusers: false,
                //是否允许选择路径。
                allowSelectPath: false,

                formType: "online"
            },
            needConfirmDlg: false,
            //控件配置
            formConfig: "",
            //表单全局配置
            globalConfig: {},
            //表单数据
            formData: {},
            //显示流程图
            isShowImage: false,
            //表单js
            formJs: "",
            //是否只读
            readonly: false,
            //表单权限
            permission:{},
            //上下文数据
            contextData:  {},
            //是否能设计表单
            canDesignForm:false,
            initFormData:{},//初始化表单数据

        }
    },
    computed: {
        //是否打开窗口。
        isOpenWindow(){
            if(this.layerid){
                return true;
            }
            return false;
        },
        ...mapState(userUser,['user']),
        parentVm(){
            let vm=this;
            while (vm && !vm.rootVm){
                vm=vm.$parent;
            }
            return vm;
        }
    },
    methods: {
        i18n(name,text,key){
            return this.$ti18(name,text,"formSolution",key);
        },
        /**
         * 获取国际化名称
         * @param item
         * @returns {*}
         */
        getI18Name(item){
            if(item.i18nJson){
                return this.$i18(item.i18nJson,item.name)||item.name;
            }
            return item.name;
        },
        changeTabs(key){
            if(key=='flowChart'){
                let formBuild=this.getFormVm();
                let data=formBuild.getData();
                //清除字段前后空格；
                Util.removeSpaces(data);
                this.formData=data;
                this.isShowImage=true;
            }else {
                this.isShowImage=false;
            }
        },
        init(){
            //先将按钮清空
            this.buttons = [];
            let action=this.readonly ? "detail":"edit";
            FormSolutionApi.getByAlias(this.formSolutionAlias, this.formPkId, this.formParams,action,this.appId).then(result => {
                if(result){
                    // 按钮定义。
                    this.buttons = this.getButtons(result);
                    this.formSolution = result.formSolution;
                    if (result.metadata) {
                        let formConfig = JSON.parse(result.metadata);
                        if (formConfig) {
                            result.formConfig = formConfig;
                        }
                        if (this.setInitData) {
                            let _data = Util.deepClone(result.data);
                            let initData = this.setInitData(_data);
                            delete initData.initData;
                            result.data = Object.assign(result.data,initData );
                        }
                        this.initForm(result);
                    }

                    this.getCanDesignForm();
                }
            });
        },
        /**
         * 初始化参数
         */
        initParams(){
            //从属性传入。
            if (this.alias) {
                this.formSolutionAlias = this.alias;
                this.formPkId = this.pkId;
                this.readonly = this.readOnly;
                this.formParams = this.params;
            }
            //从弹框打开,使用DialogView 打开
            else if (this.menuParams) {
                let json = JSON.parse(this.menuParams);
                this.formSolutionAlias = json.formAlias;
                this.formPkId = json.pkId || "";
                this.readonly = json.readOnly || false;
            }
            //从路由打开表单。
            else{
                let params;
                if (this.$route.meta.params) {
                    params = JSON.parse(this.$route.meta.params);
                    //加载参数。
                    if(this.$route.params){
                        params=Object.assign(params,this.$route.params);
                    }
                } else {
                    params = this.$route.params;
                }
                if (params.formAlias) {
                    this.formSolutionAlias = params.formAlias;
                }
                if (params.pkId) {
                    this.formPkId = params.pkId;
                }
                if(params.readOnly!=undefined){
                    this.readonly=params.readOnly || this.readOnly;
                }
                //通过只读路由打开。
                if(this.$route.name=="customFormRead"){
                    this.readonly=true;
                }
                //传入无主键参数
                if(params.params){
                    this.formParams=params.params;
                }
            }
        },
        /**
         * 初始化表单
         * @param {Object}  res 对象。
         */
        async initForm(res) {
            let user=this.user;
            var contextData = {
                type: "form",
                curUserId: user.userId,
                curUserName: user.fullName,
                account: user.account,
                deptId: user.deptId,
                tenantId: user.tenantId,
            };
            //存在instId 调用接口查询流程审批意见
            if (this.flowInstId){
               let res = await FormSolutionApi.getInstDetail(this.flowInstId)
                contextData["opinionHistorys"] = res.bpmCheckHistories
            }


            if(!this.pkId && this.formSolution && this.formSolution.flowDefMapping){
                //新增时获取绑定的流程设计主键
                let flows = JSON.parse(this.formSolution.flowDefMapping);
                let defId ="";
                if(flows && flows.length>0){
                    defId=flows[0].defId;
                }
                let contextDetail = {
                    defId: defId
                };
                Object.assign(contextData, contextDetail);
            }
            if (res.data.INST_ID_ ) {
                let contextDetail = {
                    instId: res.data.INST_ID_
                };
                Object.assign(contextData, contextDetail);
            }
            this.formJs =res.script;
            this.formConfig = res.formConfig;
            this.globalConfig = res.globalConfig? JSON.parse(res.globalConfig) : {};
            this.formData=res.data;
            this.ininFormData = res.data;
            this.formAlias=res.alias;
            this.idField=res.idField;
            this.permission=res.permission;
            this.contextData=contextData;
            this.formData = {...this.formData,...this.backfillParams}
        },
        /**
         * 计算按钮
         * @param {Object}  res 表单返回数据
         * @returns {*[]}
         */
        getButtons(res){
            let canSave = res.canSave;
            let pkId=res.data[res.idField || "ID_"];
            let instStatus=res.data.INST_STATUS_;
            this.canStartFlow=res.canStartFlow;
            this.flowInstId=res.data.INST_ID_;
            this.localDefId=res.formSolution.flowDefId;
            let context={
                canStartFlow:this.canStartFlow,
                instId:this.flowInstId,
                bpmDefId:this.localDefId,
                instStatus:instStatus,
                pkId: pkId,
                formSolution:res.formSolution
            }

            let buttons=[];
            let btns = res.buttons ? JSON.parse(res.buttons) : [];
            for (let i = 0; i < btns.length; i++) {
                let btn = btns[i];
                if(!this.readonly  && btn.modeConfig.indexOf("edit")==-1){
                    //编辑
                    continue;
                }else if(this.readonly && typeof this.readonly === "boolean" && btn.modeConfig.indexOf("detail")==-1){
                    //明细
                    continue;
                }else if(btn.type=="edit" && context.instId){
                    //编辑
                    continue;
                }else if(this.readonly && typeof this.readonly === "boolean" && btn.mode && btn.modeConfig.indexOf("detail")==-1){
                    //明细
                    continue;
                }
                else if(btn.type=="flowImage" && !context.bpmDefId && !context.instId){
                    //流程图 未配置流程时不显示
                    continue;
                }
                else if(btn.method=="startFlow" && !context.canStartFlow){
                    //启动流程
                    continue;
                }
                else if(["newSubmit","submit"].includes(btn.method) && !canSave){
                    //提交按钮
                    continue;
                }
                //保存按钮 流程已结束不允许保存
                if(btn.method==="submit" && instStatus && instStatus!='CANCEL' && instStatus!='DRAFTED'){
                    this.canStartFlow = false;
                    context.canStartFlow = this.canStartFlow;
                }
                /**
                 * 判断按钮是否可以显示。
                 */
                if(ButtonShow[btn.method]){
                    let show=ButtonShow[btn.method](context);
                    if(!show){
                        continue;
                    }
                }
                btn.loading = false;
                buttons.push(btn);
            }
            return buttons;
        },
        dataChange:Util.debounce(function (data){
            if(this.readOnly){
                return;
            }
            let self_=this;
            FormSolutionApi.getButtonsByFormJson(self_.formSolution.alias,data,this.appId).then(res=>{
                self_.buttons = self_.getButtons(res);
            })
        },500),
        //获取渲染表单对象
        getFormVm(){
            return this.$refs.formBuild.$refs.XForm;
        },
        //获取表单数据
        getFormData(){
            let formJson = {};
            let formBuild=this.getFormVm();
            formJson[this.formAlias] = formBuild.getData();
            return formJson;
        },
        /**
         * 处理按钮事件。
         * @param {Object}  btn     按钮对象。
         * @returns {Promise<void>}
         */
        async handMethod(btn,buttons) {
            btn.loading = true;
            let formBuild=this.getFormVm();
            let res = await FormSolutionApi.validPreByButton(btn.preCondConfig,JSON.stringify(formBuild.getData()));
            if(!res.success){
                btn.loading=false;
                this.$message.error(res.message);
                return;
            }
            //表单方法
            if(btn.type=="formMethod"){
                btn.loading = false;
                let method =  btn.method;
                if (formBuild && formBuild[method]) {
                    formBuild[method](this,btn);
                }
                return;
            }
            //自定义方法
            else if(btn.type=="custom"){
                let formBuild=this.getFormVm();
                let formJson = formBuild.getData();
                let config = btn.config;
                let func = new Function("FormSolutionApi","formJson","rxAjax","btn",config.action).bind(this);
                func(FormSolutionApi,formJson,rxAjax,btn);
                return;
            }
            let method=["startFlow","staging","submit"];
            if(!method.includes(btn.method)){
                btn.loading=false;
            }
            //调用预定义方法。
            if(this[btn.method]){
                this[btn.method](btn);
            }
            else{
                this.$message.warn(`${btn.method},`+this.i18n('funcJs.notDefined','还没有定义!'))
            }
        },
        /**
         * 打开页面定制配置
         * @param (Object) btn 按钮配置
         */
        openCustomView(btn){
            let formVm=this.getFormVm();
            let formJson = {};
            formJson[this.formAlias] = formVm.getData();
            let config=btn.config;
            let data=formJson[this.formAlias];
            //调用前置方法
            if (config.preMethod) {
                let rtn =  formVm[config.preMethod](data);
                if (!rtn.success) {
                    formVm.$message.warning(rtn.msg);
                    return
                }
            }
            let initData=this.customViewInitData(config,data,formVm);
            var baseConf= {
                "curVm": formVm,
                component: AppUtil.loadComponent("modules/form/FormCustomView/FormCustomView.vue"),
                title: config.name,
                max: config.isMax=='YES'?true:false,
                widthHeight: [config.width+"px", config.height+"px"],
                cancel:function(){},
                "data": {
                    "alias": config.alias,
                    "params": JSON.stringify(initData)
                }
            };
            Util.open(baseConf, function (action,data) {
                if(!config.callBack){
                    return;
                }
                /**
                 * 表单Vm
                 */
                let func=formVm[config.callBack];
                if(func){
                    func(action,data);
                }
            });
        },
        //获取打开页面自定页面的映射参数
        customViewInitData(config,data,formVm){
            var params = {};
            if (config.params && config.params.length > 0) {
                for (let i = 0; i < config.params.length; i++) {
                    var param = config.params[i];
                    if (!param.bindFieldLabel || !param.returnValue) {
                        continue;
                    }
                    if(param.mappingMode=='fixed'){
                        //输入固定值
                        params[param.bindFieldLabel] = param.returnValue;
                    }else if(param.mappingMode=='script'){
                        //脚本方法
                        let rtn =  formVm[param.returnValue](data);
                        params[param.bindFieldLabel] = rtn;
                    }else {
                        if(param.curType=="main"){
                            //主表
                            params[param.bindFieldLabel] = data[param.returnValue];
                        }else if(param.curType=='onetoone'){
                            //当前一对一子表
                            params[param.bindFieldLabel] = data['sub__'+param.curTable][param.returnValue]
                        }
                    }
                }
            }
            return params
        },
        /**
         * 打开表单方案
         * @param (Object) btn 按钮配置
         */
        openSolutionForm(btn){
            let formVm=this.getFormVm();
            let formJson = {};
            let config=btn.config.openConfig;
            let openFormConfig = btn.config.openFormConfig
            formJson[this.formAlias] = formVm.getData();
            let data=formJson[this.formAlias];
            let initData=this.getInitData(config,data,formVm);
            let self_ = this;
            DialogBox.showForm({
                title: config.formName,
                curVm: self_,
                data: {
                    alias: config.formAlias, setInitData: function (data) {
                        return Object.assign(data, initData);
                    },
                    closeOnSave:true
                },
                max: openFormConfig.isMax == "YES" ? true : false,
                shade: openFormConfig.model,
                widthHeight:[openFormConfig.width + 'px', openFormConfig.height + 'px'],

            }, function (action,data) {
                if(formVm[config.callback]){
                    formVm[config.callback](action,data);
                }
            });
        },
        /**
         * 获取绑定值
         * @param (Object) data 当前表单数据
         * @param (String) curField 当前字段
         * @param (String) bindType 绑定类型
         * @param (Object) formVm 表单vm
         * @returns (Object) 绑定的数据.
         */
        getBindValue(data,curField,bindType,formVm){
            let type = bindType || "field";
            if(type=="field"){
                return data[curField];
            }
            if(type=="fixed"){
                return curField;
            }
            if(type=="script"){
                if(!curField){
                    console.info("form method is empty");
                    return "";
                }
                if(!formVm[curField]){
                    console.info("form method is not defined,please add ["+ curField +"]");
                    return "";
                }
                return formVm[curField](data);
            }
        },
        /**
         * 根据配置 构建映射初始化数据
         * @param (Object) config 配置
         * @param data 当前表单数据
         * @returns (Object) 初始化数据
         */
        getInitData(config,data,formVm){
            let formData={};
            if(!config.formConfig){
                return formData;
            }
            //根据配置 构建映射数据
            let formConfig=JSON.parse(config.formConfig);
            //遍历表配置
            for (let i = 0; i < formConfig.length; i++) {
                let obj=formConfig[i];
                if(!obj.fieldConfig || obj.fieldConfig.length==0){
                    continue;
                }
                //目标表类型
                let targetType= obj.targetType;
                //遍历字段配置
                for (let j = 0; j < obj.fieldConfig.length; j++) {
                    let fieldConfig=obj.fieldConfig[j];
                    let fieldCurType=fieldConfig.curType;
                    let targetField =fieldConfig.targetField;
                    let curTable = "sub__"+fieldConfig.curTable;
                    let curField = fieldConfig.curField;
                    let bindType = fieldConfig.bindType || "field";
                    let targetTable= "sub__"+obj.targetTable;
                    let targetTableName = obj.targetTable;
                    //映射到主表
                    if(targetType=="main"){
                        //当前主表
                        if(fieldCurType=="main"){
                            let val=this.getBindValue(data,curField,bindType,formVm);
                            formData[targetField]=val;
                        }else  if(fieldCurType=="onetoone"){ //当前一对一子表
                            let val=this.getBindValue(data[curTable],curField,bindType,formVm);
                            formData[targetField]=val;
                        }

                    }else if(obj.targetType=="onetoone"){//映射到一对一子表
                        //一对一子表无数据时默认{}
                        formData[targetTable] = formData[targetTable] || {};
                        //当前主表
                        if(fieldConfig.curType=="main"){
                            let val=this.getBindValue(data,curField,bindType,formVm);
                            formData[targetTable][targetField]=val;
                        }else  if(fieldConfig.curType=="onetoone"){ //当前一对一子表
                            let val=this.getBindValue(data[curTable],curField,bindType,formVm);
                            formData[targetTable][targetField]=val;
                        }
                    }else if(obj.targetType=="onetomany") {//映射到一对多子表
                        formData[targetTable] = formData[targetTable] || [];
                        formData.initData = formData.initData || {};
                        //子表初始化数据
                        formData.initData[targetTableName]=formData.initData[obj.targetTable] || {};
                        //当前主表
                        if(fieldConfig.curType=="main"){
                            formData.initData[targetTableName][targetField]=data[curField];
                            let tableData=formData[targetTable];
                            if(tableData && tableData.length>0){
                                for (let k = 0; k < tableData.length; k++) {
                                    let val=this.getBindValue(data,curField,bindType,formVm);
                                    tableData[k][targetField]=val;
                                }
                            }
                        }else  if(fieldConfig.curType=="onetoone"){ //当前一对一子表
                            formData.initData[targetTableName][targetField]=data[curTable][curField];
                            let tableData=formData[targetTable];
                            if(tableData && tableData.length>0){
                                for (let k = 0; k < tableData.length; k++) {
                                    let val=this.getBindValue(data[curTable],curField,bindType,formVm);
                                    tableData[k][targetField]=val;
                                }
                            }
                        }else {//当前一对多子表
                            if(!data[curTable]){
                                continue;
                            }
                            let curTableData =data[curTable];
                            for (let k = 0; k < curTableData.length; k++) {
                                let row=curTableData[k];
                                let val=this.getBindValue(row,curField,bindType,formVm);
                                //一对多子表单行无数据时默认{}
                                if(!formData[targetTable][k]){
                                    let subRow=JSON.parse(JSON.stringify(formData.initData[targetTableName]));
                                    subRow[targetField]= val;
                                    formData[targetTable][k]=subRow;
                                }else {
                                    formData[targetTable][k][targetField]=val;
                                }
                            }
                        }
                    }
                }
            }

            return formData;
        },
        /**
         * 打开自定义表单（旧）
         * @param btn
         */
        openCustomForm(btn) {
            let self_ = this;
            let formJson = {};
            let config=btn.config;
            let formBuild=this.getFormVm();
            formJson[this.formAlias] =formBuild.getData();
            FormSolutionApi.getValueByCustomFormConfig({
                formJson: formJson,
                formConfig: config.formConfig || []
            }).then(res => {
                DialogBox.showForm({
                    title: config.formName,
                    curVm: self_,
                    data: {
                        alias: config.formAlias, setInitData: function (data) {
                            return Object.assign(data, res);
                        }
                    },
                    max: true
                }, function (action) {
                });
            })
        },

        /**
         * 路由回退
         */
        goBack(){
            router.back()
        },

        /**
         * 打开自定义组件
         * @param config
         * {
         *     path:"组件路径",
         *     title:"组件标题",
         *     width: "800px",
         *     height: "600px",
         *     callback: 需要执行的脚本，脚本时字符串格式，脚本中可以使用:
         *     formData :表单数据
         *     customData：组件返回的数据。
         *     比如脚本书写如下 :
         *     'console.info(formData)'
         * }
         */
        openCustomControl(config){
            let params = config.config ;
            //获取当前表单的数据
            let formBuild=this.getFormVm();
            let formData = formBuild.getData();
            //{ "width": "600px", "height": "400px", "model": true, "isMax": "NO" }
            let obj = {
                curVm:this,
                component:params.path,
                title:params.title,
                shade:params.model,
                data:{
                    data:formData
                }
            }
            if(params.isMax && params.isMax=='YES'){
                obj.max=true;
            }
            else {
                obj.widthHeight=[params.width,params.height];
            }
            //调用前置方法
            if (config.config.preMethod) {
                let rtn =  formBuild[config.config.preMethod](formData);
                if (!rtn.success) {
                    this.$message.warning(rtn.msg);
                    return rtn;
                }
            }
            //返回参数
            if(config.config.returnParameters){
                let rtn =  formBuild[config.config.returnParameters](formData);
                obj.data['parameters'] = rtn || {}
            }
            DialogBox.openComponent(obj,function (action,data){
                if(action == 'ok'){
                    if(formBuild && formBuild[params.callback]){
                        formBuild[params.callback](action,data)
                    }
                }
            })
        },
        /**
         * 套打。
         * @param btn
         */
        async printLodop(btn) {
            let defId=btn.config.defId;
            if (!defId) {
                this.$message.warning(this.i18n('funcJs.printLodopTips','未绑定套打模板!'));
                return;
            }
            this.lodopUtil = (await import('@/assets/js/LodopFuncs.js')).default;
            let formBuild=this.getFormVm();
            let formData = formBuild.getData();
            this.lodopUtil.onload(function(lodop){
                if (!lodop) {
                    return;
                }
                //初始化任务名称
                lodop.PRINT_INIT(btn.config.name);
                FormPrintLodopApi.printHtml({
                    pkId: defId,
                    formData: JSON.stringify(formData)
                }).then(res => {
                    eval(res.data);
                    //打印预览
                    lodop.PREVIEW();
                })
            })
        },
        /**
         * 打开列表
         */
        openCustomList(btn){
            let config=btn.config;
            //获取当前表单的数据
            let formBuild=this.getFormVm();
            let formData = formBuild.getData();
            let params=config.params
            let queryParams=[]
            let typeJson = {string: "S", int: "I", date: "D", float: "F"};
            for(let param of params){
                let srcField=param.srcField.toLowerCase();
                if(!srcField){
                    continue;
                }
                let tablePre = param.tablePre ? param.tablePre + "." : "";
                let type = typeJson[param.dataType] ? typeJson[param.dataType] : "S";
                let queryString = "Q_" + tablePre + param.destField + "_" + type + "_" + param.fieldOp;
                let tmp = queryString + "=" + formData[srcField];
                queryParams.push(tmp);
            }
            //获取数据权限
            let listConfig=JSON.parse(btn.config.listConfig);
            if (listConfig.pmtAlias){
                let pmtAlias="pmtAlias="+listConfig.pmtAlias
                queryParams.push(pmtAlias);
            }
            let self_=this
            let listConf = {
                curVm:this,
                max:listConfig.isMax == "YES" ? true : false,
                shade:listConfig.model,
            }
            if(listConfig.isMax == "NO"){
                listConf["widthHeight"] = [listConfig.width + 'px', listConfig.height + 'px']
            }
            DialogBox.dialog({key:config.alias,params:queryParams.join("&")},{...listConf},function (action,data) {
                let method=config.callBack;
                if (formBuild && formBuild[method]) {
                    formBuild[method](action,data);
                }
            });
        },

        /**
         * 处理规则引擎.
         * @param btn
         */
        handleLiteFlow(btn){
            //获取当前表单的数据
            let formData = this.getFormData();
            let config=btn.config;
            if(!config || !config.liteFlowId){
                this.$message.warning(this.i18n('funcJs.liteFlow',"未绑定规则引擎!"));
                return;
            }
            FormLiteFlowApi.executeLiteFlow(config.liteFlowId,{formData:formData}).then(res=>{

            });

        },
        /**
         * 获取是否能设计表单
         */
        getCanDesignForm(){
            let param={
                appId:this.curApp.appId,
                params:{
                    formPc:this.formSolution.formId
                }
            }
            FormPcApi.checkCanChange(param).then(res=>{
                if(res){
                    this.canDesignForm=res.formPc;
                }
            });
        },
        /**
         * 设计表单
         */
        designForm(){
            if(!this.formAlias){
                this.$message.warning(this.i18n('msg.noFormDesign',"未配置表单!"));
                return;
            }
            FormPcApi.getFormPcByAlias(this.formAlias).then(res=>{
                if(res && res.id){
                    let url = "";
                    if (res.type == "DRAG-GENBYBO"){
                        url = "/dragform/bo/"+res.id+"?appId="+res.appId;
                    }else {
                        url = "/dragform/design/"+res.id+"?appId="+res.appId;
                    }
                    window.open(url)
                }
            });

        }
    },
    watch:{
        backfillParams:{
            handler(){
                this.formData = {...this.initFormData,...this.backfillParams}
            },
            deep:true
        }
    }
}
